<template>
  <div>
    <div style="position:relative">
      <el-popover ref="treePopover" placement="bottom-start" width="250" trigger="click" v-model="open">
        <el-input size="small" class="filter-input" placeholder="请输入过滤字段" v-model.trim="filterValue" v-if="filterable">

        </el-input>
        <div class="dropdown">
          <el-tree :data="data" ref="treeField" :default-expand-all="true" :default-checked-keys="defaultCheckedKeys" :show-checkbox="multiple" :filter-node-method="filterNodeMethod" node-key="value" :expand-on-click-node="false" @node-click="nodeClick" @check-change="checkChange"></el-tree>
        </div>
      </el-popover>

      <div v-popover:treePopover class="tree-input" v-if="multiple" :class="{'show': open}">
        <div class="wrap">
          <input placeholder="请选择" v-show="!checkedNodes.length" readonly class="placeholder" />
          <el-tag v-for="item in textField" :key="item.value" size="mini" closable @close="nodeRemove($event, item)">{{item.label}}</el-tag>
        </div>
        <span class="icon">
          <i class="el-icon-arrow-down"></i>
        </span>
      </div>
      <div v-popover:treePopover v-else>
        <div>
          <el-input placeholder="请选择" :value="textField.length ? textField[0].label : '' " readonly size="small"></el-input>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import map from "lodash/map"
import indexOf from "lodash/indexOf"
import cloneDeep from "lodash/cloneDeep"

export default {
  name: "ccComboTree",
  props: {
    value: {
      type: Array,
      default: [],
    },
    data: {
      type: Array,
      default: () => []
    },
    multiple: {
      type: Boolean,
      default: false
    },
    parentOnly: {
      type: Boolean,
      default: false
    },
    filterable: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      open: false,

      style: "",
      filterValue: "",
      checkedNodes: [],
      checkedNodesClone: [],
      popoverShow: false,
      defaultCheckedKeys: []
    }
  },

  computed: {
    textField() {
      if (this.parentOnly) {
        this.checkedNodesClone = cloneDeep(this.checkedNodes)
        this.removeChildren(this.checkedNodesClone);
        this.value.splice(0, this.value.length, ...this.checkedNodesClone.map((item) => {
          return {
            value: item.value,
            label: item.label,
          }
        }))
        return this.checkedNodesClone;
      } else {
        this.value.splice(0, this.value.length, ...this.checkedNodes.map((item) => {
          return {
            value: item.value,
            label: item.label,
          }
        }))
        return this.checkedNodes;
      }
    }
  },
  watch: {
    filterValue(val) {
      this.$refs.treeField.filter(val);
    },
    value(value) {
      value = value || [];
      this.defaultCheckedKeys.splice(0, this.defaultCheckedKeys);
      value.forEach((item) => {
        this.defaultCheckedKeys.push(item.value);
      });
    },
    data() {
      this.$nextTick(() => {
        if (this.parentOnly) {
          this.checkedNodes = this.$refs.treeField.getCheckedNodes().map((item) => {
            return { value: item.value, label: item.label, children: item.children }
          })
        } else {
          this.checkedNodes = this.$refs.treeField.getCheckedNodes().filter((item) => {
            return !item.children || item.children.length <= 0;
          })
        }
      });
    }
  },
  methods: {
    filterNodeMethod(value, data, node) {
      if (!this.filterable || !value) {
        return true;
      }
      return data.label.indexOf(value) > -1;
    },
    nodeClick(obj, node, dom) {
      if (this.multiple == false && obj.children && obj.children.length > 0) {
        return;//如果禁用了该节点的复选框，则也不执行该节点的文本点击事件
      }
      if (this.multiple) {
        if (node.checked) {
          this.$refs.treeField.setChecked(obj.value, false, true);
        } else {
          this.$refs.treeField.setChecked(obj.value, true, true);
        }
      } else {
        this.checkedNodes = [obj];
        this.checkChange(obj, true);
      }
    },
    checkChange(obj, checked) {
      if (!obj.children || obj.children.length <= 0) {
        const values = map(this.checkedNodes, "value"),
          index = indexOf(values, obj.value);

        if (checked) {
          if (index <= -1) {
            this.checkedNodes.push(obj)
          }
        } else {
          if (index > -1) {
            this.checkedNodes.splice(index, 1);
          }
        }
      } else if (obj.children && obj.children.length) {
        if (this.parentOnly === true) {
          const values = map(this.checkedNodes, "value"),
            index = indexOf(values, obj.value);
          if (checked) {
            if (index <= -1) {
              this.checkedNodes.push(obj);
            }
          } else {
            if (index > -1) {
              this.checkedNodes.splice(index, 1);
            }
          }
        }
      }
    },
    nodeRemove(e, item) {
      const values = map(this.checkedNodes, "value"),
        index = indexOf(values, item.value);
      if (index > -1) {
        this.checkedNodes.splice(index, 1);
      }
      this.$refs.treeField.setChecked(item.value, false, true);
      e.stopPropagation();
    },
    /**
     * 移除子节点
     */
    removeChildren(nodes) {
      nodes.forEach((item) => {
        //加入这个元素有子节点
        if (item.children) {
          //取出所有直接点的value
          let values = item.children.map((item) => {
            return item.value;
          });

          let filterItems = this.checkedNodesClone.filter((item, index) => {
            //如果当前数据包含在其他children点中
            if (values.includes(item.value)) {
              return true;
            }
          });
          filterItems.forEach((item, index) => {
            const indexOf = this.checkedNodesClone.indexOf(item);
            //移除当前数据
            if (indexOf > -1) {
              let removedChildren = this.checkedNodesClone.splice(indexOf, 1);
              if (this.checkedNodesClone.length > 1) {
                let [removedChild] = removedChildren;
                //如果移除的的数据仍然有子节点继续执行移除节点操作
                if (removedChild && removedChild.children && removedChild.children.length) {
                  this.removeChildren([item]);
                }
              }
            }
          });
        }
      });
    }
  },
  created() {
  },
  mounted() {
    //this.value.splice(0, this.value.length, ...[{ value: 9628 }, { value: 9633 }])
  },
}
</script>

<style lang="less" scoped>
@import "./index.less";
</style>
